iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 22
0
自我挑戰組

React 30 天學習歷程系列 第 22

【Day 22】遠端資料請求方式以及 API 統一管理

  • 分享至 

  • xImage
  •  

遠端資料請求的方式有幾種,早期通常是透過原生 AJAX 或是 jQuery 包裝後的 AJAX 來請求資料,現在大多是使用 fetchaxios,兩者差別在於 fetch 是原生的 API,axios 是一個基於 AJAX 打包過後的套件,下面列出兩者的特性:

fetch

  • fetch 使用 ES6 的 Promise 作回應。
  • 使用 then 作為下一步的執行。
  • 使用 catch 當作錯誤回應。
  • 回傳值為 ReadableStream 物件,需要使用不同資料類型的對應方法取得資料物件。
  • fetch 只對網絡請求報錯,對400,500都當做成功的請求。
  • fetch 默認不會帶cookie,需要添加配置項。
  • fetch 沒有辦法原生監聽請求的進度,而XHR可以。
  • 不基於XHR,是ES新規範的實現方式。
  • fetch 跨域處理的性能比 XHR 要好。瀏覽器發送的請求是不能隨便跨域的,一定要藉助其他方式協助跨域,而 fetch 可以直接設置 mode 為「no-cors」來實現跨域訪問。

axios

  • 簡單易用。
  • 支援 Promise API。
  • 可以在 node.js 中使用,從 node.js 中創建 http 請求。
  • 提供一次多個請求(axios.all())。
  • 相當輕量,約 13kb。
  • 從瀏覽器中創建 XHR。
  • 支持攔截請求和響應。
  • 支持取消請求。
  • 客戶端支持防禦 CSRF 攻擊。

使用 fetch、axios

如前一篇所提,在 class component 請求數據,通常是在 componentDidMount 中執行,要注意的是,fetch 因為是原生 API,所以能直接使用,axios 則需要先安裝後,再 import 使用。function component 中請求數據的方式也可以參考前一篇使用 react hook 的方式。

import axios from 'axios'

class TestComponent extends React.Component {
    state = {
        data: []
    }

    async componentDidMount () {
        // fetch
        const data = await fetch('https://randomuser.me/api/', {}).then(res =>   res.json())
        if (data) {
            this.setState({data: data})
        }
        
        // axios
        const res = await axios('https://randomuser.me/api/')
        if ( result && result.data) {
            this.setState({data: result.data})
        }
    }

    render() {
        const { data } = this.state
        return (
            <div>
                { userData }
            </div>
        );
    }
}

API 統一管理

通常一個比較完善的產品,都會將 API 進行統一的管理,方便工程師進行開發和維護,不管是 fetch 或是 axios,在開發中通常都會先打包起來,讓其他工程師可以直接調用,不需要去寫許多重複的程式碼。

fetch 封裝範例

我們先建立一支 JS 檔,api.js 當作管理 API 的檔案,接著將 fetch 封裝為一個函式,裡面有兩個參數,第一個參數是使用 fetch 本身常用的一些參數配置,第二個參數是比較不常用或不會經常改動的參數配置。這個函式最後會返回 fetch 請求的結果

// api.js
export default ({ url, method, headers, data }, option = {}) => {
    return fetch(url, { // url 請求位置
        method: method || 'GET', //請求方法
        // 發送給伺服器的資料
        body: data ? JSON.stringfy(data) : null,
        headers: headers || {
            'content-type': 'application/json'
        },
        mode: 'cors', // 跨域處理
        ...option // 其他配置
    }).then(res => res.json())
}

使用的時候,我們可以在元件中引入 api.js 來調用,如下

import api from './utils/api.js'

const getData = api({ url: '/api/userData', data: { id: 'userId' } })

封裝 axios

也是先建立一支 JS 檔做管理,一樣封裝成一個函式,最後會返回請求結果,函式的參數同樣分為常用配置和不常用配置,封裝完畢後,一樣可以在元件中進行調用。

export default ({ url, method, headers, data }, option = {}) => {
    return fetch(url, { // url 請求位置
        method: method || 'GET', //請求方法
        // 發送給伺服器的資料
        data,
        headers: headers || {
            'content-type': 'application/json'
        },
        ...options
    })
}

集中請求 API

上面雖然有將 API 請求的基本方式做封裝了,但如果直接就在各個元件中進行請求,在管理上仍然非常麻煩,因此通常會按照不同類型的功能,區分為不同的檔案進行資料請求。

下面的案例我們建立一個 user.js,所有和 user 資料相關的請求都會在這個檔案內執行,像是 getAllUser()getUser(id) 都是單純的取得資料,就繼續使用 GET 方法,如果是像 addUser 這種新增或更新資料的情況,就使用 POST。這邊使用 static,是因為靜態屬性不需要實例化也可以調用,可以減少內存的配置。

import api from './utils/api.js'

export default class user {
    // 取得所有用戶
    static getAllUser() {
        return api({
            url: '/api/allUser'
        })
    }
    
    // 取得當前用戶
    static getUser(id) {
        return api({
            url: '/api/user/${id}'
        })
    }
    
    // 新增用戶
    static addUser(data) {
        return api({
            url: '/api/addUser',
            methid: 'POST',
            data
        })
    }
}

之後我們只要在元件中進行調用即可。

import userApi from '../service/user'

class UserProfile extends React.Component {
    state = {
        user: []
    }

    async componentDidMount () {
        const user = await userApi.getUser('userId')
        if (user) {
            this.setState({user: user})
        }
    }

    render() {
        const { user } = this.state
        return (
            <div>
                { user }
            </div>
        );
    }
}

小結

由於課程對 fetchaxios 的介紹比較少,這篇文章中使用了一些自己之前做的筆記,因為當時有參考網路上的文章,所以在下面附上參考資料。

參考資料


上一篇
【Day 21】React 中請求遠端資料
下一篇
【Day 23】React 的高級特性
系列文
React 30 天學習歷程30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言